export default class Mat4 {
    matrix: Float32Array = new Float32Array(16);
    constructor(
        m00: number | Float32Array = 1, m01: number = 0, m02: number = 0, m03: number = 0,
        m10: number = 0, m11: number = 1, m12: number = 0, m13: number = 0,
        m20: number = 0, m21: number = 0, m22: number = 1, m23: number = 0,
        m30: number = 0, m31: number = 0, m32: number = 0, m33: number = 1,
    ) {
        let m = this.matrix;
        if (m00 instanceof Float32Array) {
            m = m00;
        } else {
            m[0] = m00; m[1] = m01; m[2] = m02; m[3] = m03;
            m[4] = m10; m[5] = m11; m[6] = m12; m[7] = m13;
            m[8] = m20; m[9] = m21; m[10] = m22; m[11] = m23;
            m[12] = m30; m[13] = m31; m[14] = m32; m[15] = m33;
        }

    }
    static mul(out: Mat4, a: Mat4, b: Mat4) {
        let outm = out.matrix, am = a.matrix, bm = b.matrix;
        outm[0] = am[0] * bm[0] + am[1] * bm[4] + am[2] * bm[8] + am[3] * bm[12];
        outm[1] = am[0] * bm[1] + am[1] * bm[5] + am[2] * bm[9] + am[3] * bm[13];
        outm[2] = am[0] * bm[2] + am[1] * bm[6] + am[2] * bm[10] + am[3] * bm[14];
        outm[3] = am[0] * bm[3] + am[1] * bm[7] + am[2] * bm[11] + am[3] * bm[15];
        return out;
    }

    static mulScaler(out: Mat4, num: number) {
        let m = out.matrix;
        m[0] *= num; m[1] *= num; m[2] *= num; m[3] *= num;
        m[4] *= num; m[5] *= num; m[6] *= num; m[7] *= num;
        m[8] *= num; m[9] *= num; m[10] *= num; m[11] *= num;
        m[12] *= num; m[13] *= num; m[14] *= num; m[15] *= num;
        return this;
    }
    static copy(out: Mat4, a: Mat4) {
        let m = out.matrix, am = a.matrix;
        m[0] = am[0];
        m[1] = am[1];
        m[2] = am[2];
        m[3] = am[3];
        m[4] = am[4];
        m[5] = am[5];
        m[6] = am[6];
        m[7] = am[7];
        m[8] = am[8];
        m[9] = am[9];
        m[10] = am[10];
        m[11] = am[11];
        m[12] = am[12];
        m[13] = am[13];
        m[14] = am[14];
        m[15] = am[15];
        return out;
    }
    mul(a: Mat4) {
        return Mat4.mul(this, this, a);
    }
    mulScalar(num: number) {
        return Mat4.mulScaler(this, num);
    }
}